home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The X-Philes (2nd Revision)
/
The X-Philes Number 1 (1995).iso
/
xphiles
/
hp48hor2
/
fft7.src
< prev
next >
Wrap
Text File
|
1992-08-18
|
29KB
|
875 lines
(Comp.sources.hp48)
Item: 140 by kcooke@milton.u.washington.edu [Ken Cooke]
Subj: Machine Code FFT source code
Date: 14 Jul 1992
I'm glad to hear that someone liked the machine code FFT programs.
In response to email requests, here is the SASM source code. It can
be assembled with the HP tools. I didn't include FFT, because it is a
subset of IFFT (I commented the lines to remove).
I apologize for the shortage of higher-level comments (most of this is
still on paper). Also, I traded some readability to avoid subroutine calls
(hardware stack levels are very precious) and keep variables in registers.
A few of the ROM calls are "unsupported entry points", which may need
fixing in the future. With rumors of new 48's in the works, ones with
machine code Eqn Writers, re-written plotter user interfaces, and maybe
even faster Saturn processors...well, lets just say that it may be wise to
stick to entries listed in ENTRIES.A.
I hope this is of use to someone interested in ML math software. While I
like playing games on my 48 as much as the next guy, it would be nice to
see more math tools using the capabilities of sys-RPL and ML. (I do,
occasionally, use my 48 as a calculating device :) Unfortunately,
there is no documentation on using the low-level floating point routines
(MULTF, RADDF, etc) so a little hacking with Voyager or MLDL is required.
I would love to hear from other math-hackers out there...
Ken Cooke
N7VFE
kcooke@u.washington.edu
----------
* ANGLE.S WORKS FOR ANY SIZE VECTOR OR ARRAY
* Copyright 1992 Ken Cooke
* Takes a VECTOR/ARRAY in STK1. Returns a real VECTOR/ARRAY of
* same size, that contains the angle of each complex element,
* according to the current trig mode.
TITLE ANGLE
ASSEMBLE
NIBASC /HPHP48-A/
RPL
::
CK1NoBlame
CK&DISPATCH1
FOUR
::
* IF REAL ARRAY, EXIT UNCHANGED
DUP TYPECARRY? NOT?SEMI ( ORIG )
* MALLOC ANSWER ARRAY (SAME SIZE AS ORIG BUT REAL )
DUP MDIMS ITE TWO{}N ONE{}N %0 MAKEARRY ( ORIG ANS )
CODE
****************** UNLISTED ENTRY POINTS *****************
ATTN?Lp = #0CA88
ARG15 = #2B6D7
SetTrigMode = #2AEF6
************************ MCODE ANGLE ***********************
* ENTRY:
* STK2: ORIGINAL ARRY1 (COMPLEX)
* STK1: ANSWER ARRY (REAL)
* EXIT: STK1: ANSWER ARRAY (REAL)
NIBHEX 823 ;CLEAR SB AND XM IN HST
D1=D1+ 5 ;DROP STK1
D=D+1 A ;RETURN MEM
GOSBVL =SAVPTR ;SAVE REGS WITH ONLY orig ON STACK
A=DAT1 A ;A->ORIG
D1=D1- 5 ;POINT BACK TO ANS
C=DAT1 A ;C->ANS
R3=C.F A ;SAVE ->ANS IN R3
D0=C
D0=D0+ 15
D0=D0+ 10 ;D0->ANS DATA (OR DIM2 IF ARRAY)
D1=A ;D1->ORIG
D1=D1+ 15 ;D1->#DIMS
A=DAT1 A ;A=#DIMS
D1=D1+ 5 ;D1->DIM1
C=DAT1 A ;C=DIM1
D1=D1+ 5 ;D1->ORIG DATA (OR DIM2 IF ARRAY)
A=A-1 A ;CHECK FOR VECTOR
?A=0 A
GOYES ISVECT
***IF ARRAY, #ELEMENTS=DIM1*DIM2. ALSO, SKIP OVER DIM2 FIELD
A=DAT1 A ;A=DIM2
D1=D1+ 5 ;D1->ORIG DATA
D0=D0+ 5 ;D0->ANS DATA
SETHEX
GOSBVL =MUL# ;B=A*C
C=B A ;C=DIM1*DIM2
ISVECT C=C-1 A ;SUB 1 SO CAN USE BORROW FOR LOOPING
R4=C.F A ;SAVE #ELEMENTS-1 IN R4
ABSLOOP GOSBVL =ATTN?Lp ;ABORT IF ATTN (ON) WAS PRESSED
A=DAT1 W ;A=RE
D1=D1+ 16 ;D1->IM
CD0EX
RSTK=C ;PUSH D0
C=DAT1 W ;C=IM
D1=D1+ 16 ;D1->NEXT RE
SETDEC
GOSBVL =SPLTAC ;CONVERT BOTH TO LONGS
GOSBVL =SetTrigMode ;SET ST ACCORDING TO TRIG MODE FLAGS
GOSBVL =ARG15 ;AB=ANGLE (TRASHES A,B,C,D,D0,R0,R1)
GOSBVL =PACK ;A=ABSVAL
C=RSTK
D0=C ;POP D0
DAT0=A W ;STORE ABSVAL IN ANSWER ARRAY
D0=D0+ 16 ;POINT AT NEXT ANSWER
* CHECK FOR DONE
C=R4.F A ;GET COUNTER
SETHEX
C=C-1 A
R4=C.F A ;DEC COUNTER
GONC ABSLOOP ;LOOP UNTIL BORROW
***NOW ANSWER CONTAINS ABS VALUES OF ORIG
A=R3.F A
GOSBVL =GPOverWrALp ;GETPTR, REPLACE TOS WITH ANS, LOOP
ENDCODE
;
;
END_SRC
BEGIN_SRC ifft.s
******************************************************************
* MACHINE CODE IFFT by Ken Cooke
* Copyright 1992
******************************************************************
* RADIX-2 DIT IFFT
* Input: real or complex vector on STK1, with size=2^n
* Ouput: complex vector containing IFFT
* Note: uses the definition that FFT uses exp(-xxx) and IFFT uses exp(+xxx)
TITLE IFFT
ASSEMBLE
NIBASC /HPHP48-A/
RPL
::
CK1NoBlame
CK&DISPATCH1
FOUR
::
DUP MDIMS ( ARRY #N flag )
* CHECK FOR MATRIX (NcaseDIMERR = 37DF6 )
NOT NcaseDIMERR ( ARRY #N )
* CHECK FOR SIZE=2^N
DUP ( ARRY #N #N )
CODE
****************** CHECK THAT SIZE=POWER OF TWO **************
*CHKSIZE2 REPLACES BINT (ON TOS) WITH TRUE IF BINT IS A
* POWER OF 2, FALSE OTHERWISE.
*NOTE: WORKS UP TO 2^19, AND RETURNS TRUE FOR BINT=0
WrTLoop EQU #03B1A
WrFLoop EQU #03B06
C=DAT1 A ;C->BINT
CD1EX ;SAVE D1 IN C.A
D1=D1+ 5 ;D1->DATA
A=DAT1 A ;A.A=BINT
D1=C ;RESTORE D1
SETHEX
C=A A
A=-A-1 A ;A=ONES COMP
C=-C A ;C=TWOS COMP
A=A!C A ;NO ZEROS IF BINT=2^N
A=A+1 A ;WILL SET CARRY IF BINT=2^N
GOC DoTrue
GOVLNG WrFLoop ;OVERWRITE BINT WITH FALSE AND CONT
DoTrue GOVLNG WrTLoop ;OVERWRITE BINT WITH TRUE AND CONT
ENDCODE
* ( ARRY #N FLAG )
NcaseDIMERR ( IF FALSE THEN "INVALID DIMENSION" ERROR )
* IF SIZE=1, RETURN WITH ARRY ON STACK
DUP#1= ITE DROP ( ARRY #N )
::
* CREATE TEMP STORAGE (MUST BE 172 NIBS BIGGER THAN UNPACKED A FOR VARS)
FORTYTWO OVER #* 172 #+ MAKEHEX$ SWAP ( ARRY HEX$ #N )
ONE{}N C%0 MAKEARRY ( ARRY HEX$ ANSARRY )
* DO THE FFT
CODE
****************** UNLISTED ENTRY POINTS *****************
PUTAB1 = #2C066
GETCD1 = #2C017
aSIN15 = #2B6E0
ATTN?Lp = #0CA88
longpi = #2A45D
varnibs = 172
************************ MCODE FFT ***********************
* ENTRY:
* STK3: (orig) real/complex data array
* STK2: (temp) hex$ (to hold vars and unpacked reals during FFT)
* STK1: (ans) complex answer array
* EXIT: STK1: complex FFT array (ans)
NIBHEX 823 ;CLEAR SB AND XM IN HST
D1=D1+ 10 ;DROP temp AND ans
D=D+1 A ;RETURN MEM
D=D+1 A
GOSBVL =SAVPTR ;SAVE REGS WITH ONLY orig ON STACK
* SAVE NEEDED POINTERS IN SCRATCH REGS
D1=D1- 5 ;POINT BACK TO temp
A=DAT1 A ;A->temp
A=A+CON A,10 ;SKIP HEADER TO vars
R4=A.F A ;R4->vars
P= 0 ;*****REMEMBER:ALWAYS HAVE P=0 BEFORE LC(5)*****
LC(5) varnibs ;
SETHEX
A=A+C A ;SKIP OVER VARS
R1=A.F A ;R1->data
D1=D1+ 5 ;POINT TO orig
A=DAT1 A ;A->orig
D0=A
D0=D0+ 10 ;D0->OBJ PROLOG
* SET FLAG IF REAL, FOR USE WHEN UNPACKING
* USE D.15 INSTEAD OF ST TO AVOID TROUBLE
D=0 S ;USE D.15 AS FLAG (0=COMPLEX,1=REAL)
A=DAT0 A ;A=OB PROLOG
LC(5) #02977 ;C=COMPLEX PROLOG
?A=C A
GOYES CMPLEX
D=D+1 S ;IF REAL, D.15=1
CMPLEX D0=D0+ 10 ;D0->SIZE
A=DAT0 A ;A.A=SIZE
R2=A.F A ;STORE SIZE IN R2
D0=D0+ 5 ;D0->DATA
CD0EX
R0=C.F A ;R0->origdata
*FIND LOG2 OF SIZE
C=0 S ;C.S WILL HOLD SIZE2=LOGbase2(SIZE)
LOG2LP ASRB.F A
C=C+1 S
?ABIT=0 0
GOYES LOG2LP
R2=C.F S ;STORE SIZE2 IN R2.15
*************************** BITREV AND UNPACK ****************************
*NOW, CONVERT REALS IN orig INTO EXT.REALS IN data
* AT THE SAME TIME, REARRANGE INTO BIT-REVERSED ORDER
A=R0.F A
D0=A ;D0->origdata
D=0 A ;D HOLDS INDEX INTO orig (START AT 0)
BITREV CPEX 15 ;PUT BIT-COUNTER IN P
P=P-1 ;SUB ONE SO CAN USE BORROW FOR BITLOOP
C=D A ;C GETS INDEX INTO orig
B=0 A ;B WILL BE BIT-REV INDEX
*BIT REVERSAL
BITLOOP B=B+B A ;SHIFT B LEFT ONE BIT
?CBIT=0 0 ;TEST LSB
GOYES NOCARRY ;SKIP IF ZERO
B=B+1 A ;ELSE FEED INTO B
NOCARRY CSRB.F A ;SHIFT C RIGHT ONE BIT
P=P-1 ;DEC BIT-COUNTER (BORROW WHEN DONE)
GONC BITLOOP ;LOOP IF MORE
*MULT B (BITREV INDEX) BY 21 AND ADD TO ->data
A=B A ;COULD USE =MUL# BUT THIS IS FASTER/SHORTER
B=B+B A
B=B+B A ;B=4B
A=A+B A ;A=5B
B=B+B A
B=B+B A ;B=16B
B=A+B A ;B=21B
B=B+B A ;B=42B
A=R1.F A ;A->data
A=A+B A ;
D1=A ;D1 POINTS INTO data AT BITREV POSITION
A=DAT0 W ;GET RE(Ai)
D0=D0+ 16 ;POINT AT NEXT REAL
GOSBVL =SPLITA ;NO NEED TO SETDEC (DONE IN SPLITA)
GOSBVL =PUTAB1 ;PUT LONG AT DAT1, D1+=21
* IF INPUT ARRAY WAS REAL, USE IMAG=0
?D=0 S ;IF COMPLEX
GOYES GETIM ; GET IMAG PART
A=0 W ;ELSE USE IMAG=0
B=0 W
GONC NOGETIM ;GO ALWAYS
GETIM A=DAT0 W ;GET IM(Ai)
D0=D0+ 16
GOSBVL =SPLITA
NOGETIM GOSBVL =PUTAB1 ;STORE IMAG PART
SETHEX
D=D+1 A ;INC INDEX
C=R2 ;LOAD SIZE AND SIZE2 INTO C
?D=C A ;COMPARE INDEX TO SIZE
GOYES BITDONE
GOTO BITREV ;REPEAT IF NOT DONE
BITDONE
********** data NOW HOLDS LONG BITREV ARRAY **********
******************** BUTTERFLIES *******************
* ENTRY: temp CONTAINS BIT-REV LONG COMPLEX DATA
* A IS NO LONGER NEEDED
* Define template for var storage: (var names from Num.Recipes)
istep = 0
n = (istep)+5
mmax = (n)+5
data0 = (mmax)+5
wr = (data0)+5
wi = (wr)+21
tempr = (wi)+21
wtemp = (tempr)+21
theta = (wtemp)+21
wpi = (theta)+21
wpr = (wpi)+21
m = (wpr)+21
*FIRST, STORE SCRATCH REGS IN VARS
SETHEX
A=R4.F A ;A->istep
D1=A
D1=D1+ 5 ;D1->n
C=R2.F A ;C=size
C=C+C A ;C=2*size
DAT1=C A ;n=2*size
D1=D1+ 5 ;D1->mmax
P= 0
LC(5) #2 ;C=2
DAT1=C A ;mmax=2
D1=D1+ 5 ;D1->data0 ***STORE POINTER TO data[0] HERE
C=R1.F A ;***THIS CORRECTS FOR "FORTRAN INDEXING"
C=C-CON A,16 ;*** SINCE ALGORITHM ASSUMES INDEXES START AT 1
C=C-CON A,5 ;*** I.E. data[1] = data0+21 = FIRST SPOT
DAT1=C A
**REDUCED TO ONE SINE/MAINLOOP BY USING wtemp TO HOLD LAST SIN(theta)
** AND CALCULATING SIN(theta/2)
LC(5) wtemp ;INIT wtemp TO AVOID SIN(PI) SINCE NOT RETURN ZERO
C=C+A A ;A STILL =R4
D0=C ;D0->wtemp
A=0 W
B=0 W ;AB=0.0
GOSBVL =PUTAB0 ;STORE wtemp=0.0, D0->theta
**INIT theta TO -pi FOR FFT, +pi FOR IFFT
D1=(5) =longpi
GOSBVL =GETAB1 ;get pi from ROM
* SETDEC *********enable for FFT
* A=-A-1 S ;A=-PI *********enable for FFT
GOSBVL =PUTAB0 ;STORE IN theta
************************ BEGIN MAIN LOOP ***********************
MAINLOOP
C=R4.F A ;C->vars
D1=C
D1=D1+ 5 ;D1->n
C=DAT1 A ;C=n
D1=D1+ 5 ;POINT AT mmax
A=DAT1 A ;A=mmax
* MAINLOOP TEST
?A<C A ;IF (mmax>=n)
GOYES MAINCONT ; THEN DONE
GOTO MAINDONE
** A=mmax, D1->mmax
MAINCONT
SETHEX
A=A+A A ;A=2*mmax
D1=D1- 10 ;istep
DAT1=A A ;STORE istep=2*mmax
D1=D1+ 10
D1=D1+ 10 ;D1->wr
A=0 W
B=0 W
P= 14 ;CREATE AB=1.0
B=B+1 P
GOSBVL =PUTAB1 ;STORE wr=1.0, D1->wi
B=0 P
GOSBVL =PUTAB1 ;STORE wi=0.0, D1->tempr
D1=D1+ 16
D1=D1+ 5 ;D1->wtemp
CD1EX
RSTK=C ;PUSH ->wtemp
D0=C ;D0->wtemp
D1=C ;D1->wtemp
D1=D1+ 16
D1=D1+ 16
D1=D1+ 10 ;D1->wpi
SETDEC :***NOTE: SETDEC BEFORE ALL FP MATH (WILL STAY IN DEC)
GOSBVL =GETAB0 ;AB=wtemp, D0->theta
GOSBVL =PUTAB1 ;STORE wpi=wtemp, D1->wpr
GOSBVL =GETAB0 ;AB=theta, D0->wpi
GOSBVL =DIV2 ;AB=theta/2
D0=D0- 16
D0=D0- 5 ;D0->theta
GOSBVL =PUTAB0 ;STORE theta=theta/2
ST=1 9 ;SET UP FOR SIN (IN RADIANS)
ST=0 4
GOSBVL =aSIN15 ;**NOTE:TRASHES A,B,C,D,P,D0,R0,R1!!!
C=RSTK ;POP ->wtemp
D0=C ;D0->wtemp
GOSBVL =PUTAB0 ;STORE wtemp=SIN(theta)
C=B W
D=C W ;CD=AB
C=A W
GOSBVL =MULTF ;SQUARE wtemp
C=B W
D=C W ;CD=AB
C=A W
GOSBVL =RADDF ;DOUBLE AB (D0 TRASHED)
A=-A-1 S ;NEGATE AB
GOSBVL =PUTAB1 ;STORE wpr=-2*SQR(wtemp), D1->m
A=0 A
A=A+1 B ;A=1
DAT1=A A ;STORE m=1
************************ BEGIN OUTER LOOP ***********************
OUTLOOP SETHEX
A=R4.F A
D0=A
D0=D0+ 10 ;D0->mmax
P= 0
LC(5) m
C=C+A A
D1=C ;D1->m
A=DAT0 A ;A=mmax
C=DAT1 A ;C=m
*OUTLOOP TEST
?C<A A ;IF (m>=mmax)
GOYES NOTDONE ; THEN DONE
GOTO OUTDONE
NOTDONE RSTK=C ;PUSH i=m (i KEPT ON TOS)
A=R4.F A
D1=A ;D1->n-5
************************ BEGIN INNER LOOP ***********************
INLOOP
GOSBVL =ATTN?Lp ;IF ATTN(ON) HAS BEEN PRESSED, GETPTR AND LOOP
D1=D1+ 5 ;D1->n
A=DAT1 A ;A=n
C=RSTK ;C=i
*INLOOP TEST
?C<=A A ;IF (i>n)
GOYES INCONT ; THEN DONE
GOTO INDONE
INCONT RSTK=C ;PUSH i BACK
D1=D1+ 5 ;D1->mmax
A=DAT1 A ;A=mmax
SETHEX
A=A+C A ;A=j
B=A A
B=B+B A
B=B+B A
A=A+B A
B=B+B A
B=B+B A
A=A+B A ;A=21*j
B=C A
C=C+C A
C=C+C A
B=B+C A
C=C+C A
C=C+C A
B=C+B A ;B=21*i
D1=D1+ 5 ;D1->data0
C=DAT1 A ;C->data
A=A+C A ;A->data[j]
C=B+C A ;C->data[i]
RSTK=C ;PUSH ->data[i]
C=A A
RSTK=C ;PUSH ->data[j]
D1=D1+ 5 ;D1->wr
D0=C ;D0->data[j]
GOSBVL =GETAB1 ;AB=wr, D1->wi
GOSBVL =STAB2 ;SAVE wr IN R2/R3
GOSBVL =GETCD0 ;CD=data[j], D0->data[j+1]
SETDEC
GOSBVL =MULTF ;AB=wr*data[j]
GOSBVL =STAB0 ;SAVE IN R0/R1
GOSBVL =GETAB1 ;AB=wi, D1->tempr
GOSBVL =GETCD0 ;CD=data[j+1]
GOSBVL =MULTF ;AB=wi*data[j+1]
GOSBVL =RCCD0 ;CD=wr*data[j]
A=-A-1 S ;NEGATE AB
GOSBVL =RADDF ;AB=RESULT (D0 TRASHED)
GOSBVL =PUTAB1 ;tempr=RESULT, D1->tempi
C=RSTK
RSTK=C ;COPY ->data[j] FROM TOS
D0=C ;D0->data[j]
GOSBVL =GETCD0 ;CD=data[j], D0->data[j+1]
D1=D1- 16
D1=D1- 16
D1=D1- 10 ;D1->wi
GOSBVL =GETAB1 ;AB=wi
GOSBVL =MULTF
GOSBVL =STAB0 ;STORE wi*data[j] IN R0/R1
GOSBVL =GETCD0 ;CD=data[j+1]
GOSBVL =RCAB2 ;AB=wr
GOSBVL =MULTF ;AB=wr*data[j+1]
GOSBVL =RCCD0 ;CD=wi*data[j]
GOSBVL =RADDF ;AB=tempi (D0 TRASHED)
GOSBVL =STAB0 ;SAVE tempi IN R0/R1
C=RSTK
***STORE D1=>data[j]
D1=C ;D1->data[j]
C=RSTK
RSTK=C ;COPY ->data[i] FROM TOS
C=C+CON A,16
C=C+CON A,5 ;C->data[i+1]
RSTK=C ;PUSH ->data[i+1]
D0=C
GOSBVL =GETCD0 ;CD=data[i+1]
GOSBVL =STCD2 ;SAVE data[i+1] IN R2/R3
A=-A-1 S ;NEGATE tempi
GOSBVL =RADDF ;AB=data[i+1] - tempi
CD1EX
D1=C ;C->data[j]
D0=C
D0=D0+ 16
D0=D0+ 5 ;D0->data[j+1]
GOSBVL =PUTAB0 ;STORE data[j+1]
GOSBVL =RCAB0 ;AB=tempi
GOSBVL =RCCD2 ;CD=data[i+1]
GOSBVL =RADDF ;AB=tempi+(data[i+1])
C=RSTK ;POP ->data[i+1]
D0=C ;D0->data[i+1]
GOSBVL =PUTAB0 ;STORE data[i+1]
A=R4.F A
P= 0
LC(5) tempr
SETHEX
A=A+C A
D0=A ;D0->tempr
GOSBVL =GETAB0 ;AB=tempr
GOSBVL =STAB0 ;STORE tempr IN R0/R1
C=RSTK
RSTK=C ;COPY ->data[i] FROM TOS
D0=C ;D0->data[i]
GOSBVL =GETCD0 ;CD=data[i]
GOSBVL =STCD2 ;SAVE data[i] IN R2/R3
SETDEC
A=-A-1 S ;NEGATE tempr
GOSBVL =RADDF ;AB=data[i]-tempr
**USE D1=>data[j]
GOSBVL =PUTAB1 ;STORE data[j]
GOSBVL =RCAB0 ;AB=tempr
GOSBVL =RCCD2 ;CD=data[i]
GOSBVL =RADDF ;AB=data[i]+tempr
C=RSTK ;POP ->data[i]
D0=C ;D0->data[i]
GOSBVL =PUTAB0 ;STORE data[i]
A=R4.F A
D1=A ;D1->istep
A=DAT1 A ;A=istep
C=RSTK ;POP i
SETHEX
C=C+A A ;i=i+istep
RSTK=C ;PUSH NEW i
GOTO INLOOP ;NEXT ITERATION
************************ END INNER LOOP ***********************
INDONE
A=R4.F A
P= 0
LC(5) wr
SETHEX
C=C+A A
RSTK=C ;PUSH *wr
D0=C ;D0->wr
LC(5) wpr
C=C+A A
D1=C ;D1->wpr
SETDEC
GOSBVL =GETAB0 ;AB=wr
GOSBVL =STAB0 ;SAVE OLDwr IN R0/R1
GOSBVL =GETCD1 ;CD=wpr, D1->wpr+21
GOSBVL =MULTF ;AB=wr*wpr
GOSBVL =STAB2 ;SAVE IN R2/R3
GOSBVL =GETCD0 ;CD=wi
D1=D1- 16
D1=D1- 16
D1=D1- 10 ;D1->wpi
GOSBVL =GETAB1 ;AB=wpi, D1->wpr
GOSBVL =MULTF ;AB=wi*wpi
A=-A-1 S ;NEGATE AB
GOSBVL =RCCD2 ;CD=wr*wpr
GOSBVL =RADDF ;AB=wr*wpr - wi*wpi (D0 TRASHED)
GOSBVL =RCCD0 ;CD=OLDwr
GOSBVL =RADDF ;AB=RESULT (D0 TRASHED)
C=RSTK ;POP *wr
D0=C ;D0->wr
GOSBVL =PUTAB0 ;STORE NEW wr, D0->wi
D1=D1- 16
D1=D1- 5 ;D1->wpi
GOSBVL =GETAB1 ;AB=wpi, D1->wpr
GOSBVL =RCCD0 ;CD=OLDwr
GOSBVL =MULTF ;AB=OLDwr*wpi
GOSBVL =STAB0 ;SAVE IN R0/R1
GOSBVL =GETCD0 ;CD=wi
GOSBVL =STCD2 ;SAVE wi IN R2/R3
GOSBVL =GETAB1 ;AB=wpr, D1->m
GOSBVL =MULTF ;AB=wpr*wi
GOSBVL =RCCD0 ;CD=OLDwr*wpi
GOSBVL =RADDF ;AB=wpr*wi + OLDwr*wpi (D0 TRASHED)
GOSBVL =RCCD2 ;CD=wi
GOSBVL =RADDF ;AB=RESULT
C=R4.F A
D0=C
D0=D0+ 16
D0=D0+ 16
D0=D0+ 9 ;D0->wi
GOSBVL =PUTAB0 ;STORE NEW wi
C=DAT1 A ;C=m
SETHEX
C=C+1 A
C=C+1 A ;m=m+2
DAT1=C A ;STORE NEW m
GOTO OUTLOOP ;NEXT ITERATION
************************ END OUTER LOOP ***********************
OUTDONE SETHEX ;D0 STILL POINTS TO mmax, A=mmax
A=A+A A ;A=2*mmax
DAT0=A A ;STORE NEW mmax
GOTO MAINLOOP
************************ END MAIN LOOP ***********************
MAINDONE
* temp NOW HOLDS vars (FIRST 172 NIBS) AND LONG COMPLEX ARRAY OF ANSWERS
***************** PACK AND COPY INTO ans *****************
A=R4.F A
D1=A ;D1->vars
D1=D1+ 5 ;D1->n
A=DAT1 A ;A=n
R2=A.F A ;SAVE n IN R2 (COUNTER IN PACKLOOP)
***REMOVE FOR FFT
ASRB.F A ;A=size
************* CONVERT A.A INTO EXT.REAL ************
* USING HORNER'S RULE, 10100 = 2^4 + 2^2 = ((((1)2+0)2+1)2+0)2+0
* SINCE THE *2 AND ADDITION IS DONE IN DEC, RESULT IN DEC
* ENTER: BINT IN A.A (ANY)
* EXIT: EXT.REAL IN A/B (DEC)
* TRASHES: A,B,C,P
P= 0
LCHEX 19 ;REPEAT FOR EACH BIT IN A.A
B=0 W ;B WILL HOLD MANTISSA
BITLP B=B+B W ;B*=2
SETHEX
A=A+A A ;SHIFT MSB OF BINT INTO CARRY
SETDEC
GONC SKIP
B=B+1 W
SKIP C=C-1 B ;DEC BIT COUNTER
GONC BITLP
P= 5 ;A.A IS 0 FROM SHIFTING IN ZEROS
A=A-1 X
NORMLP A=A+1 X ;A ACCUM'S EXPONENT BY COUNTING DIGITS
BSRC ;ROTATE UNTIL MANT IS LEFT-JUSTIFIED
?B#0 WP
GOYES NORMLP
BSR W ;SHIFT MANT INTO PLACE (B.S=0)
A=0 S ;SIGN IS POSITIVE
* AB NOW HOLDS EXT.REAL
**************** END OF CONVERSION ****************
GOSBVL =STAB0 ;SAVE SIZE IN R0/R1
*******REMOVE FOR FFT
SETHEX
A=R4.F A ;**THIS IS THE LAST TIME WE USE R4(temp)
P= 0
LC(5) varnibs ;SKIP OVER VARS TO DATA
C=A+C A ;C->data
D0=C ;D0->data (SOURCE OF COPY)
D1=(5) =DSKTOP ;RECALL SAVED D1
C=DAT1 A
D1=C ;D1->STK3 (orig)
D1=D1- 10 ;D1->STK1 (ans)
C=DAT1 A
R3=C.F A ;SAVE ->ans IN R3
D1=C ;D1->ans
D1=D1+ 15 ;SKIP HEADER
D1=D1+ 10 ;D1->ansdata (DEST OF COPY)
* NOW PACK AND COPY
* NOTE: OVER/UNDERFLOW ERRORS ARE TRAPPED IN =PACK. orig IS SAVED AS TOS
PAKLOOP
GOSBVL =GETAB0 ;GET NEXT LONG
GOSBVL =RCCD0 ;RECALL SIZE *REMOVE FOR FFT
SETDEC
GOSBVL =DIVF ;DIVIDE BY SIZE *REMOVE FOR FFT
GOSBVL =PACK ;EXT.REAL->REAL
DAT1=A W ;PUT REAL IN PLACE
D1=D1+ 16 ;POINT AT NEXT REAL
C=R2.F A ;GET COUNTER
SETHEX
C=C-1 A ;DEC COUNTER
R2=C.F A
?C#0 A
GOYES PAKLOOP
* NOW RESULT IS PACKED INTO ans ARRAY
* AT LAST, REPLACE STK1 (ORIGINAL ARRAY) WITH RESULT ARRAY
A=R3.F A ;A->ans
GOVLNG =GPOverWrALp ;RESTORE REGS, PUT @A ON TOS, CONT RPL
ENDCODE
;
;
;
END_SRC
BEGIN_SRC absv.s
* ABSV.S WORKS FOR ANY SIZE VECTOR OR ARRAY
* Copyright 1992 Ken Cooke
* Takes a VECTOR/ARRAY in STK1. Returns a real VECTOR/ARRAY of
* same size, that contains the element-by-element absolute values.
TITLE ABSV
ASSEMBLE
NIBASC /HPHP48-A/
RPL
::
CK1NoBlame
CK&DISPATCH1
FOUR
::
* IF REAL ARRAY, EXIT UNCHANGED
DUP TYPECARRY? NOT?SEMI ( ORIG )
* MALLOC ANSWER ARRAY (SAME SIZE AS ORIG BUT REAL )
DUP MDIMS ITE TWO{}N ONE{}N %0 MAKEARRY ( ORIG ANS )
CODE
****************** UNLISTED ENTRY POINTS *****************
ATTN?Lp = #0CA88
SQR15 = #2B9F3
************************ MCODE ABSV ***********************
* ENTRY:
* STK2: ORIGINAL ARRY1 (COMPLEX)
* STK1: ANSWER ARRY (REAL)
* EXIT: STK1: ANSWER ARRAY (REAL)
NIBHEX 823 ;CLEAR SB AND XM IN HST
D1=D1+ 5 ;DROP STK1
D=D+1 A ;RETURN MEM
GOSBVL =SAVPTR ;SAVE REGS WITH ONLY orig ON STACK
* NOW IF USER HITS "ON" KEY, WILL LEAVE ORIGINAL STACK
A=DAT1 A ;A->ORIG
D1=D1- 5 ;POINT BACK TO ANS
C=DAT1 A ;C->ANS
R0=C.F A ;SAVE ->ANS IN R0
D0=C
D0=D0+ 15
D0=D0+ 10 ;D0->ANS DATA (OR DIM2 IF ARRAY)
D1=A ;D1->ORIG
D1=D1+ 15 ;D1->#DIMS
A=DAT1 A ;A=#DIMS
D1=D1+ 5 ;D1->DIM1
C=DAT1 A ;C=DIM1
D1=D1+ 5 ;D1->ORIG DATA (OR DIM2 IF ARRAY)
A=A-1 A ;CHECK FOR VECTOR
?A=0 A
GOYES ISVECT
***IF ARRAY, #ELEMENTS=DIM1*DIM2. ALSO, SKIP OVER DIM2 FIELD
A=DAT1 A ;A=DIM2
D1=D1+ 5 ;D1->ORIG DATA
D0=D0+ 5 ;D0->ANS DATA
SETHEX
GOSBVL =MUL# ;B=A*C
C=B A ;C=DIM1*DIM2
ISVECT C=C-1 A ;SUB 1 SO CAN USE BORROW FOR LOOPING
R4=C.F A ;SAVE #ELEMENTS-1 IN R4
ABSLOOP GOSBVL =ATTN?Lp ;ABORT IF ATTN (ON) WAS PRESSED
SETDEC
GOSUB SQDAT1 ;SQUARE RE PART
GOSBVL =STAB2 ;SAVE IN R2/R3
GOSUB SQDAT1 ;SQUARE IM PART
CD0EX
RSTK=C ;PUSH D0
GOSBVL =RCCD2 ;CD=SQR(RE)
GOSBVL =RADDF ;AB=SQR(RE)+SQR(IM) (D0 TRASHED)
GOSBVL =SQR15 ;AB=LONG ABSVAL
GOSBVL =PACK ;A=ABSVAL
C=RSTK
D0=C ;POP D0
DAT0=A W ;STORE ABSVAL IN ANSWER ARRAY
D0=D0+ 16 ;POINT AT NEXT ANSWER
* CHECK FOR DONE
C=R4.F A ;GET COUNTER
SETHEX
C=C-1 A
R4=C.F A ;DEC COUNTER
GONC ABSLOOP ;LOOP UNTIL BORROW
***NOW ANSWER CONTAINS ABS VALUES OF ORIG
GOVLNG =GPOverWrR0Lp ;GETPTR, REPLACE TOS WITH ANS, LOOP
************************ SQDAT1 ***********************************
* GET REAL FROM DAT1, UNPACK AND SQUARE IT, INC D1
SQDAT1 A=DAT1 W ;A=REAL
D1=D1+ 16 ;D1->NEXT
GOSBVL =SPLITA ;AB=REAL
C=B W
D=C W
C=A W ;COPY INTO CD
GOSBVL =MULTF ;AB=SQR(REAL)
RTN
ENDCODE
;
;